#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <wait.h>
#include <string.h>
#include <errno.h>
#include "net.h"
#include "debug_printf.h"

void doInit(Socket *s);
int doGetMessage(Socket *s);

Socket *makeSocket(void) {
	Socket *s = (Socket*) malloc(sizeof(Socket));

	s->init = doInit;
	s->getMessage = doGetMessage;

	return s;
}

void doInit(Socket *this) {

  this->opt=1;
  this-> master_socket;
  struct sockaddr_in address;

  this->max_clients = 3;

  this->tv.tv_sec = 0;
  this->tv.tv_usec = 100;

  strcpy(this->message, "Data-relay v0.1 (C)1996 Simon Amor <simon@foobar.co.uk>\n\r");

/* initialise all client_socket[] to 0 so not checked */
  for (this->loop = 0; this->loop < this->max_clients; this->loop++) {
    this->client_socket[this->loop] = 0;
  }

/* create the master socket and check it worked */
  if ((this->master_socket = socket(AF_INET,SOCK_STREAM,0))==0) {
/* if socket failed then display error and exit */
    perror("Create master_socket");
    exit(EXIT_FAILURE);
  }

/* set master socket to allow multiple connections */
  if (setsockopt(this->master_socket, SOL_SOCKET, SO_REUSEADDR, 
                 (char *)&this->opt, sizeof(this->opt))<0) {
    perror("setsockopt");
    exit(EXIT_FAILURE);
  }

/* type of socket created */
  this->address.sin_family = AF_INET;
  this->address.sin_addr.s_addr = INADDR_ANY;
/* 7000 is the port to use for connections */
  this->address.sin_port = htons(7000);
/* bind the socket to port 7000 */
  if (bind(this->master_socket, (struct sockaddr *)&this->address, sizeof(this->address))<0) {
/* if bind failed then display error message and exit */
    perror("bind");
    exit(EXIT_FAILURE);
  }

/* try to specify maximum of 3 pending connections for the master socket */
  if (listen(this->master_socket, 3)<0) {
/* if listen failed then display error and exit */
    perror("listen");
    exit(EXIT_FAILURE);
  }



  /****
	int loop, opt = 1;
  this->max_clients = MAXLOG;

  this->tv.tv_sec = 0;
  this->tv.tv_usec = 100;

  strcpy(this->message, "Data-relay v0.1 (C)1996 Simon Amor <simon@foobar.co.uk>\n\r");

  for (loop = 0; loop < this->max_clients; loop++) {
    this->client_socket[loop] = 0;
  }

  if ((this->master_socket = socket(AF_INET,SOCK_STREAM,0))==0) {
    perror("Create master_socket");
    exit(EXIT_FAILURE);
  }

  if (setsockopt(this->master_socket, SOL_SOCKET, SO_REUSEADDR, 
                 (char *)&opt, sizeof(opt))<0) {
    perror("setsockopt");
    exit(EXIT_FAILURE);
  }

  this->address.sin_family = AF_INET;
  this->address.sin_addr.s_addr = INADDR_ANY;
  this->address.sin_port = htons(DEFAULT_PORT);
  if (bind(this->master_socket, (struct sockaddr *)&this->address, sizeof(this->address))<0) {
    perror("bind");
    exit(EXIT_FAILURE);
  }

  if (listen(this->master_socket, 3) < 0) {
    perror("listen");
    exit(EXIT_FAILURE);
  }
  ****/
}

int doGetMessage(Socket *this) {

   FD_ZERO(&this->readfds);
/* reason we say max_clients+3 is stdin,stdout,stderr take up the first 
 * couple of descriptors and we might as well allow a couple of extra.
 * If your program opens files at all you will want to allow enough extra.
 * Another option is to specify the maximum your operating system allows.
 */

/* setup which sockets to listen on */
   FD_SET(this->master_socket, &this->readfds);
    for(this->loop=0; this->loop<this->max_clients; this->loop++) {
      if (this->client_socket[this->loop] > 0) {
        FD_SET(this->client_socket[this->loop], &this->readfds);
      }
    }

/* wait for connection, forever if we have to */
    this->activity = select(this->max_clients + 3, &this->readfds, NULL, NULL, &this->tv);
  
    if((this->activity < 0) && (errno!=EINTR)) {
/* there was an error with select() */

    }

    if(FD_ISSET(this->master_socket, &this->readfds)) {
/* Open the new socket as 'new_socket' */
      this->addrlen=sizeof(this->address);
      if((this->new_socket = accept(this->master_socket, (struct sockaddr *)&this->address, &this->addrlen))<0)
      {
/* if accept failed to return a socket descriptor, display error and exit */
        perror("accept");
        exit(EXIT_FAILURE);
      }
/* inform user of socket number - used in send and receive commands */
      printf("New socket is fd %d\n",this->new_socket);
  
/* transmit message to new connection */
      if(send(this->new_socket, this->message, strlen(this->message), 0) != strlen(this->message)) {
/* if send failed to send all the message, display error and exit */
        perror("send");
      }
      puts("Welcome message sent successfully");
/* add new socket to list of sockets */
      for(this->loop=0; this->loop < this->max_clients; this->loop++) {
        if(this->client_socket[this->loop] == 0) {
          this->client_socket[this->loop] = this->new_socket;
          printf("Adding to list of sockets as %d\n", this->loop);
          this->loop = this->max_clients;
        }
      }
    }

    for(this->loop = 0; this->loop < this->max_clients; this->loop++) {
      if(FD_ISSET(this->client_socket[this->loop], &this->readfds)) {
        if((this->valread = read(this->client_socket[this->loop], this->buffer, 2048)) < 0) {
          close(this->client_socket[this->loop]);
          this->client_socket[this->loop] = 0;
        }
		else {
/* set the terminating NULL byte on the end of the data read */
          this->buffer[this->valread] = 0;
          for (this->loop2=0; this->loop2<this->max_clients; this->loop2++) {
/* note, flags for send() are normally 0, see man page for details */
            send(this->client_socket[this->loop2], this->buffer, strlen(this->buffer), 0);
          }
        }
/* 
 * use read() to read from the socket into a buffer using something
 * similar to the following:
 *
 * If the read didn't cause an error then send buffer to all 
 * client sockets in the array - use for loop and send() just
 * as if you were sending it to one connection
 *
 * important point to note is that if the connection is char-by-char
 * the person will not be able to send a complete string and you will
 * need to use buffers for each connection, checking for overflows and
 * new line characters (\n or \r)
 */
      }
	  else
		  D("%s\n", strerror(errno));
    }


	/***
	int activity, valread, loop, loop2, addrlen;

    FD_ZERO(&this->readfds);

    FD_SET(this->master_socket, &this->readfds);
    for (loop = 0; loop < this->max_clients; loop++) {
      if (this->client_socket[loop] > 0) {
        FD_SET(this->client_socket[loop], &this->readfds);
      }
    }

    activity = select(this->max_clients+3, &this->readfds, NULL, NULL, &this->tv);
  
    if ((activity < 0) && (errno!=EINTR)) {
		perror("some error in select function\n");
		return;
    }
    if (FD_ISSET(this->master_socket, &this->readfds)) {
      addrlen = sizeof(this->address);
      if ((this->new_socket = accept(this->master_socket, (struct sockaddr *)&this->address, &addrlen))<0)
      {
        perror("accept");
        exit(EXIT_FAILURE);
      }
      printf("New socket is fd %d\n", this->new_socket);
  
      if (send(this->new_socket, this->message, strlen(this->message), 0) != strlen(this->message)) {
        perror("send");
      }
      puts("Welcome message sent successfully");
      for (loop=0; loop<this->max_clients; loop++) {
        if (this->client_socket[loop] == 0) {
          this->client_socket[loop] = this->new_socket;
          printf("Adding to list of sockets as %d\n", loop);
          loop = this->max_clients;
        }
      }
    }
	else
		D("Nao tou conseguindo select\n");
	D("%s\n", strerror(errno));

    for (loop=0; loop < this->max_clients; loop++) {
      if (FD_ISSET(this->client_socket[loop], &this->readfds)) {
        if ((valread = read(this->client_socket[loop], this->buffer, 1024)) < 0) {
          close(this->client_socket[loop]);
          this->client_socket[loop] = 0;
        } else {
          this->buffer[valread] = 0;
          for (loop2=0; loop2<this->max_clients; loop2++) {
            send(this->client_socket[loop2], this->buffer, strlen(this->buffer), 0);
          }
        }
      }
    }
	****/
}


